/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.imenu.web.service.mobile;

import com.imenu.ejb.ImenuCourseFacade;
import com.imenu.ejb.ImenuCustomerFacade;
import com.imenu.ejb.ImenuFavoriteFacade;
import com.imenu.ejb.ImenuMenuFacade;
import com.imenu.ejb.ImenuOrderFacade;
import com.imenu.ejb.ImenuOrderItemFacade;
import com.imenu.ejb.ImenuTagFacade;
import com.imenu.entity.ImenuCourse;
import com.imenu.entity.ImenuCustomer;
import com.imenu.entity.ImenuFavorite;
import com.imenu.entity.ImenuMenu;
import com.imenu.entity.ImenuOrder;
import com.imenu.entity.ImenuOrderItem;
import com.imenu.entity.ImenuTag;
import com.imenu.entity.OrderStatus;
import com.imenu.terminal.TerminalContentServer;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;

/**
 *
 * @author Yunzi
 */
@WebServlet(name = "JsonServlet", urlPatterns = {"/json"})
public class JsonServlet extends HttpServlet {

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            String command = request.getParameter("command");
            System.out.println("JsonServlet.processRequest() command = " + command);
            if ("favoriteMenu".equals(command)) {
                this.favoriteMenu(request, response);
            } else if ("menu".equals(command)) {
                this.menu(request, response);
            } else if ("course".equals(command)) {
                this.course(request, response);
            } else if ("commit".equals(command)) {
                this.commit(request, response);
            } else if ("order".equals(command)) {
                this.order(request, response);
            } else if ("customerInfo".equals(command)) {
                this.customerInfo(request, response);
            } else if ("customerInfoSave".equals(command)) {
                this.customerInfoSave(request, response);
            } else if ("favorite".equals(command)) {
                this.favorite(request, response);
            } else if ("cancelFavorite".equals(command)) {
                this.cancelFavorite(request, response);
            } else if ("menuCategories".equals(command)) {
                this.menuCategories(request, response);
            } else if ("coursesList".equals(command)) {
                this.coursesList(request, response);
            } 
        } finally {
            out.close();
        }
    }
    @EJB
    ImenuOrderFacade orderFacade;
    @EJB
    ImenuCourseFacade courseFacade;
    @EJB
    ImenuOrderItemFacade orderItemFacade;
    @EJB
    ImenuCustomerFacade customerFacade;

    
    @EJB
    ImenuTagFacade categoryFacade;

    private void coursesList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("JsonServlet.coursesList request.getParameter(\"menuId\")=" + request.getParameter("menuId"));
        System.out.println("JsonServlet.coursesList request.getParameter(\"tagId\")=" + request.getParameter("tagId"));
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            List<ImenuCourse> courses = new ArrayList<ImenuCourse>();
            String menuIdParam = request.getParameter("menuId");
            String tagParam = request.getParameter("tagId");
            if(tagParam == null){
                ImenuMenu menu = menuFacade.find(Integer.valueOf(menuIdParam));
                courses = courseFacade.findByMenu(menu);
            }else{
                Integer tagId = Integer.valueOf(tagParam);
                ImenuTag category = categoryFacade.find(tagId);
                courses = courseFacade.findByTag(category);
            }
            List<Map> courses4Json = new ArrayList<Map>();
            for (ImenuCourse course : courses) {
                Map map = new TreeMap<String, Object>();
                map.put("id", course.getId());
                map.put("tagId", course.getTag().getId());
                map.put("menuId", course.getMenu().getId());
                map.put("name", course.getName());
                map.put("price", course.getPrice());
                map.put("updateTime", course.getUpdateTime().getTime());
                map.put("createTime", course.getCreateTime().getTime());
                String imageType = course.getPortraitImage().substring(course.getPortraitImage().lastIndexOf("."));
                List<String> portraitImages = new ArrayList<String>();
                portraitImages.add("75x100_course_" + course.getId() + "_portrait" + imageType);
                portraitImages.add("300x400_course_" + course.getId() + "_portrait" + imageType);
                map.put("portraitImages", portraitImages);
                List<String> landscapeImages = new ArrayList<String>();
                imageType = course.getLandscapeImage().substring(course.getLandscapeImage().lastIndexOf("."));
                landscapeImages.add("100x75_course_" + course.getId() + "_landscape" + imageType);
                landscapeImages.add("300x225_course_" + course.getId() + "_landscape" + imageType);
                landscapeImages.add("440x330_course_" + course.getId() + "_landscape" + imageType);
                map.put("landscapeImages", landscapeImages);
                courses4Json.add(map);
            }
            JSON json = JSONSerializer.toJSON(courses4Json);
            out.println(json);
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }
    }
    
    
    private void menuCategories(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("MobileServlet.menuCategories request.getParameter(\"menuId\")=" + request.getParameter("menuId"));
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            Integer menuId = Integer.valueOf(request.getParameter("menuId"));
            List<ImenuTag> categories = categoryFacade.findByMenuId(menuId);//到底一个店铺是否支持多个菜单，值得商榷
            List<Map> categories4Json = new ArrayList<Map>();
            for(ImenuTag tag : categories){
                categories4Json.add(categoryItemToMap(tag));
            }
            out.println(JSONSerializer.toJSON(categories4Json));
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }
    }
    private Map categoryItemToMap(ImenuTag item) {
        TreeMap<String, Object> map = new TreeMap<String, Object>();
        map.put("id", item.getId());
        map.put("storeId", item.getStoreId().getId());
        map.put("name", item.getName());
        map.put("description", item.getDescription());
        map.put("updateTime", item.getUpdateTime().getTime());
        return map;
    }

    
    private void customerInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("MobileServlet.favorite request.getParameter(\"deviceId\")=" + request.getParameter("deviceId"));
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            ImenuCustomer customer = customerFacade.findByDeviceId(request.getParameter("deviceId"));
            out.println(JSONSerializer.toJSON(customer));
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }
    }
    @EJB
    ImenuFavoriteFacade favoriteFacade;

    private void favorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("MobileServlet.favorite request.getParameter(\"menuId\")=" + request.getParameter("menuId"));
        System.out.println("MobileServlet.Favorite request.getParameter(\"deviceId\")=" + request.getParameter("deviceId"));
        Integer menuId = Integer.valueOf(request.getParameter("menuId"));
        String deviceId = request.getParameter("deviceId");
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            ImenuCustomer customer = customerFacade.findByDeviceId(deviceId);
            if (customer == null) {
                out.println(jsonError("请先填写个人信息，然后才能收藏菜单。"));
                return;
            }
            ImenuFavorite favorite = new ImenuFavorite();
            favorite.setMenuId(menuId);
            favorite.setCustomerId(customer.getId());
            favoriteFacade.create(favorite);
            
            forward(request,response,"/mobile?command=menuList&deviceId="+deviceId);
            
            /*
            Map<String, Object> map = new TreeMap<String, Object>();
            map.put("success", true);
            map.put("message", "收藏成功。");
            map.put("favoriteId", favorite.getId());
            out.println(JSONSerializer.toJSON(map));
             */
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }
    }

    private void cancelFavorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("MobileServlet.cancelFavorite request.getParameter(\"favoriteId\")=" + request.getParameter("favoriteId"));
        System.out.println("MobileServlet.cancelFavorite request.getParameter(\"deviceId\")=" + request.getParameter("deviceId"));
        Integer favoriteId = Integer.valueOf(request.getParameter("favoriteId"));
        String deviceId = request.getParameter("deviceId");
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            favoriteFacade.remove(favoriteId);
            //out.println(jsonSuccess("取消收藏成功。"));
            forward(request,response,"/mobile?command=menuList&deviceId="+deviceId);
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }
    }

    private void customerInfoSave(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("MobileServlet.favorite request.getParameter(\"deviceId\")=" + request.getParameter("deviceId"));
        String deviceId = request.getParameter("deviceId");
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            ImenuCustomer customer = customerFacade.findByDeviceId(request.getParameter("deviceId"));
            if (customer == null) {
                customer = new ImenuCustomer();
                customer.setDeviceId(deviceId);
                customer.setAlipayName(request.getParameter("alipay"));
                customer.setMobile(request.getParameter("mobile"));
                customer.setNickname(request.getParameter("nickname"));
                customerFacade.create(customer);
            } else {
                customer.setAlipayName(request.getParameter("alipay"));
                customer.setMobile(request.getParameter("mobile"));
                customer.setNickname(request.getParameter("nickname"));
                customerFacade.edit(customer);
            }
            out.println(JSONSerializer.toJSON(customer));
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }

    }

    private void commit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String courseIds = request.getParameter("courses");
        String menuId = request.getParameter("menuId");
        String deviceId = request.getParameter("deviceId");
        String tableNo = request.getParameter("tableNo");
        System.out.println("JsonServlet.commit() tableNo=" + tableNo + " menuId=" + menuId + " courseIds = " + courseIds + " deviceId = " + deviceId);
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            //imenu_order[id, amount, store_id, customer_id, create_time]
            //imenu_order_item [Id,order_id,course_id,course_name,course_price,create_time]
            ImenuMenu menu = menuFacade.find(Integer.valueOf(menuId));
            ImenuOrder order = new ImenuOrder();
            order.setStatus(OrderStatus.NEW.getValue());
            order.setStoreId(menu.getStore().getId());
            order.setCustomerId(deviceId);
            order.setCreateTime(new java.util.Date());
            System.out.println("JsonServlet.commit() order.getId() = " + order.getId());
            orderFacade.create(order);
            System.out.println("JsonServlet.commit() order.getId() = " + order.getId());
            StringBuilder content = new StringBuilder();
            content.append(createLine(menu.getStore().getBrandName())).append("\r\n");
            content.append(createLine("桌号：" + tableNo)).append("\r\n");
            content.append(createLine(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()))).append("\r\n");
            System.out.println("JsonServlet.commit() content = " + content);
            String[] courseIdsArray = courseIds.split(",");
            int amount = 0;
            for (String id : courseIdsArray) {
                ImenuCourse course = courseFacade.find(Integer.valueOf(id));
                if(course == null){
                    System.out.println("找不到菜．（menuId="+menuId+", courseId="+id+"）");
                    continue;
                }
                ImenuOrderItem orderItem = new ImenuOrderItem();
                orderItem.setCourseId(course.getId());
                orderItem.setCourseName(course.getName());
                orderItem.setCoursePrice(course.getPrice());
                orderItem.setOrderId(order);
                orderItem.setCreateTime(new java.util.Date());
                //orderItemFacade.create(orderItem);
                amount += course.getPrice();
                order.getOrderItemsCollection().add(orderItem);
                content.append(createLine(orderItem.getCourseName(), orderItem.getCoursePrice())).append("\r\n");
            }
            order.setAmount(amount);
            orderFacade.edit(order);
            Map<String, Object> map = new TreeMap<String, Object>();
            map.put("success", true);
            map.put("order", orderToMap(order));
            //发送消息给终端设备，执行打印过程
            content.append(createLine("合计：" + amount + "元")).append("\r\n");
            System.out.println("JsonServlet.commit() TerminalContentServer.getInstance() = " + TerminalContentServer.getInstance());
            try {
                TerminalContentServer.getInstance().sendMessageToClient(order.getStoreId(), content.toString());
            } catch (Exception e) {
                out.println(jsonError("提交成功，但打印失败。"));
                e.printStackTrace();
            }
            System.out.println("JsonServlet.commit() content = " + content);
            out.println(JSONSerializer.toJSON(map));
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }
    }

    private String createLine(String name) {
        int length = name.getBytes().length;
        int part = (32 - length) / 2;
        String tail = "................................".substring(0, part);
        return tail + name + tail;
    }

    private String createLine(String name, Integer price) {
        int length = name.getBytes().length;
        String ps = price.toString() + ".00";
        length += ps.length();
        return name + "................................".substring(0, 32 - length) + ps;
    }
    @EJB
    ImenuMenuFacade menuFacade;

    private void favoriteMenu(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("JsonServlet.menu request.getParameter(\"deviceId\")=" + request.getParameter("deviceId"));
        List<ImenuMenu> menuList = menuFacade.findFavorite(request.getParameter("deviceId"));
        
        System.out.println("JsonServlet.menu menuList="+menuList); 
        System.out.println("JsonServlet.menu menuList.size() = "+menuList.size()); 
        
        String imagePath = this.getImagePath(request);
        System.out.println("imagePath = " + imagePath);

        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            List<Map> menu4Json = new ArrayList<Map>();
            for (ImenuMenu menu : menuList) {
                menu4Json.add(this.menuToMap(menu, imagePath));
            }
            System.out.println(JSONSerializer.toJSON(menu4Json));
            out.println(JSONSerializer.toJSON(menu4Json));
        } catch (Exception e) {
            out.println(jsonError(e.getMessage()));
        }

    }
    private void menu(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("JsonServlet.menu request.getParameter(\"menuId\")=" + request.getParameter("menuId"));
        Integer menuId = Integer.valueOf(request.getParameter("menuId"));
        ImenuMenu menu = menuFacade.find(menuId);
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        String imagePath = this.getImagePath(request);
        out.println(JSONSerializer.toJSON(this.menuToMap(menu, imagePath)));
    }
    
    private Map orderItemToMap(ImenuOrderItem item) {
        TreeMap<String, Object> map = new TreeMap<String, Object>();
        map.put("id", item.getId());
        map.put("orderId", item.getOrderId().getId());
        map.put("courseId", item.getCourseId());
        map.put("courseName", item.getCourseName());
        map.put("createTime", item.getCreateTime().getTime());
        map.put("coursePrice", item.getCoursePrice());
        return map;
    }

    private void order(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Integer orderId = Integer.valueOf(request.getParameter("orderId"));
        System.out.println("JsonServlet.order() orderId = " + orderId);
        ImenuOrder order = orderFacade.find(orderId);
        List<ImenuOrderItem> orderItems = orderItemFacade.findByOrderId(order);
        System.out.println("JsonServlet.order() order = " + order);
        System.out.println("JsonServlet.order() orderItems = " + orderItems);
        //System.out.println("JsonServlet.order() order.getOrderItemsCollection() = "+order.getOrderItemsCollection());

        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        try {
            List<Map> orderItem4Json = new ArrayList<Map>();
            for (ImenuOrderItem item : orderItems) {
                orderItem4Json.add(this.orderItemToMap(item));
            }
            System.out.println("orderItem4Json.size() = " + orderItem4Json.size());
            System.out.println(JSONSerializer.toJSON(orderItem4Json));
            out.println(JSONSerializer.toJSON(orderItem4Json));
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }

    }

    private TreeMap<String, Object> orderToMap(ImenuOrder order) {
        TreeMap<String, Object> map = new TreeMap<String, Object>();
        map.put("id", order.getId());
        map.put("storeId", order.getStoreId());
        map.put("customerId", order.getCustomerId());
        map.put("createTime", order.getCreateTime().getTime());
        return map;
    }

    private TreeMap<String, Object> menuToMap(ImenuMenu menu, String imagePath) {
        TreeMap<String, Object> map = new TreeMap<String, Object>();
        map.put("id", menu.getId());
        map.put("storeId", menu.getStore().getId());
        map.put("title", menu.getTitle());
        map.put("name", menu.getName());
        map.put("imagePath", imagePath + "/" + menu.getId());//${item.id}/menu_${item.id}_portrait_75x100.JPG
        String imageType = menu.getImagePortrait().substring(menu.getImagePortrait().lastIndexOf("."));
        map.put("coverImage", "300x400_cover_" + menu.getId() + "_portrait" + imageType);
        //在服务器端转换，给出图片地址，便于客户端应对变化
        map.put("updateTime", menu.getUpdateTime().getTime());
        return map;
    }

    private void course(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        String menuIdParam = request.getParameter("menuId");
        PrintWriter out = response.getWriter();
        try {
            if (menuIdParam == null) {
                throw new Exception("需要参数menuId。");
            }
            int menuId = Integer.valueOf(menuIdParam);
            ImenuMenu menu = menuFacade.find(menuId);
            Collection<ImenuCourse> courses = menu.getImenuCourseCollection();
            String imagePath = this.getImagePath(request);
            Map<String, Object> aMenu = new TreeMap<String, Object>();
            aMenu.put("menu", this.menuToMap(menu, imagePath));
            //为了便于展示，将菜品按照菜品分类，分别组织为不同的List
            Map<ImenuTag, Map<String, Object>> coursesAsTag = new HashMap<ImenuTag, Map<String, Object>>();

            for (ImenuCourse course : courses) {
                Map map = new TreeMap<String, Object>();
                map.put("id", course.getId());
                map.put("menuId", menu.getId());
                map.put("name", course.getName());
                map.put("price", course.getPrice());
                map.put("updateTime", course.getUpdateTime().getTime());
                map.put("createTime", course.getCreateTime().getTime());
                String imageType = course.getPortraitImage().substring(course.getPortraitImage().lastIndexOf("."));
                List<String> portraitImages = new ArrayList<String>();
                portraitImages.add("75x100_course_" + course.getId() + "_portrait" + imageType);
                portraitImages.add("300x400_course_" + course.getId() + "_portrait" + imageType);
                map.put("portraitImages", portraitImages);
                List<String> landscapeImages = new ArrayList<String>();
                imageType = course.getLandscapeImage().substring(course.getLandscapeImage().lastIndexOf("."));
                landscapeImages.add("100x75_course_" + course.getId() + "_landscape" + imageType);
                landscapeImages.add("300x225_course_" + course.getId() + "_landscape" + imageType);
                landscapeImages.add("440x330_course_" + course.getId() + "_landscape" + imageType);
                map.put("landscapeImages", landscapeImages);
                //在服务器端转换，给出图片地址，便于客户端应对变化
                if (coursesAsTag.get(course.getTag()) == null) {
                    coursesAsTag.put(course.getTag(), new TreeMap<String, Object>());
                    coursesAsTag.get(course.getTag()).put("courses", new ArrayList<Map>());
                }
                coursesAsTag.get(course.getTag()).put("imagePath", imagePath + "/" + menu.getId());//${item.id}/menu_${item.id}_portrait_75x100.JPG
                coursesAsTag.get(course.getTag()).put("tagId", course.getTag().getId());
                coursesAsTag.get(course.getTag()).put("tagName", course.getTag().getName());
                ((List<Map>) coursesAsTag.get(course.getTag()).get("courses")).add(map);
            }
            List<Map<String, Object>> coursesList = new ArrayList<Map<String, Object>>();
            for (Map<String, Object> value : coursesAsTag.values()) {
                coursesList.add(value);
            }
            aMenu.put("courses", coursesList);
            JSON json = JSONSerializer.toJSON(aMenu);
            System.out.println("json=" + json);
            out.println(json);
        } catch (Exception e) {
            e.printStackTrace();
            out.println(jsonError(e.getMessage()));
        }
    }
    
    private void forward(HttpServletRequest request, HttpServletResponse response, String url) throws ServletException, IOException {
        String path = url;
        System.out.println("MobileServlet.forward() path = " + path);
        getServletContext().getRequestDispatcher(path).forward(request, response);
    }

    private String getImagePath(HttpServletRequest request) {
        String imagePath = "http://" + request.getServerName() + ":" + request.getServerPort() + getServletContext().getContextPath() + "/images";
        return imagePath;
    }

    private JSON jsonError(String message) {
        Map<String, Object> map = new TreeMap<String, Object>();
        map.put("success", false);
        map.put("message", message);
        return (JSONSerializer.toJSON(map));
    }

    private JSON jsonSuccess(String message) {
        Map<String, Object> map = new TreeMap<String, Object>();
        map.put("success", true);
        map.put("message", message);
        return (JSONSerializer.toJSON(map));
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
